package com.sinodata.bsm.center.web.action.resource;

import java.util.*;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import com.sinodata.bsm.center.bean.ResBean;

import com.sinodata.bsm.center.util.web.Struts2Utils;
import com.sinodata.bsm.center.user.UserUtil;
import com.sinodata.bsm.common.vo.*;
import com.sinodata.bsm.center.web.action.resource.tree.*;

public class MotitypeTreeAction extends AbstractTreeAction {
    @Override
    protected JSONArray children() throws Exception {
        JSONArray jsonArray = new JSONArray();
        Set<Long> relationTypeIds = resRelationService.getSelfAndSubRelationTypeIds();
        String[] ids = id.split("[|]");
        if (ids[0].equals(String.valueOf(TreeConstants.NODE_TYPE_MONITORTYPE))) {
            long mtId = Long.parseLong(ids[1]);
            List<ResGroup> groups = resGroupCache.findByMoitTypeId(mtId);
            Map<Long, List<ResGroup>> tmpMap = new HashMap<Long, List<ResGroup>>();
            List<ResGroup> rootResGroup = new ArrayList<ResGroup>();
            if (groups == null) {
                groups = new ArrayList<ResGroup>(0);
            }
            List<Long> clickMonitorCache = (List<Long>) request.getSession().getAttribute("clickedMoiType");
            clickMonitorCache.add(mtId);
            for (ResGroup g : groups) {
                if (g.getParentId() != null) {
                    List<ResGroup> arr = tmpMap.get(g.getParentId().longValue());
                    if (arr == null) {
                        arr = new ArrayList<ResGroup>();
                        tmpMap.put(g.getParentId().longValue(), arr);
                    }
                    arr.add(g);
                } else {
                    rootResGroup.add(g);
                }
            }
            Set<Long> includeList = new HashSet<Long>();
            for (ResGroup g : rootResGroup) {
                JSONObject json = genResGroupNode(g, tmpMap, relationTypeIds, includeList, new ArrayList(0));
                jsonArray.add(json);
            }
            Collection<Res> ress = resService.findAll();
            for (Res res : ress) {
                Long mt = resTypeCache.getMoitTypeId(res.getResTypeId());
                if (mt == null || mt.longValue() != mtId || includeList.contains(res.getId().longValue())) {
                    continue;
                }
                if (NodePrivilegeUtil.hasResViewPrivilege(res.getId(), relationTypeIds, request)) {
                    jsonArray.add(genResNode(res, 0L, relationTypeIds));
                }
            }
        } else {
            String[] idArray = this.id.split("[|]");
            JSONArray children = loadChildNode(Long.parseLong(idArray[1]), relationTypeIds);
            NodeCompare.sortChildNodeSequence(this.id, children);
            jsonArray = children;
        }
        return jsonArray;
    }

    @Override
    protected JSONArray root() throws Exception {
        JSONArray jsonArray = new JSONArray();
        Set<Long> relationTypeIds = resRelationService.getSelfAndSubRelationTypeIds();
        try {
            Map<String, Integer[]> statusMap = NodePrivilegeUtil.getStatusCache(request, this.viewId);
            if (statusMap.size() > 0) {
                statusMap.clear();
            }
            request.getSession().setAttribute("clickedMoiType", new ArrayList<Long>());
            List<MonitorType> mtList = resViewService.findAllMonitorType();
            Collection<Res> ress = resService.findAll();
            Set<Long> set = new HashSet<Long>();
            Map<Long, Integer[]> maxStatus = new HashMap<Long, Integer[]>();
            List<String> nodeTrace = NodePrivilegeUtil.findResNodeTrace(request, this.viewId);
            long mtTraceId = 0;
            if (nodeTrace.size() > 1) {
                String[] mtarr = nodeTrace.get(0).split("[|]");
                mtTraceId = Long.parseLong(mtarr[1]);
            }
            List<Res> traceResList = new ArrayList<Res>();
            for (Res res : ress) {
                Long mtval = resTypeCache.getMoitTypeId(res.getResTypeId());
                if (mtval == null) {
                    continue;
                }
                if (NodePrivilegeUtil.hasResViewPrivilege(res.getId(), relationTypeIds, request)) {

                    set.add(mtval);
                    if (maxStatus.containsKey(mtval)) {
                        if (maxStatus.get(mtval)[0] < res.getHealthStatus()) {
                            maxStatus.get(mtval)[0] = res.getHealthStatus();
                        }
                        maxStatus.get(mtval)[1] = maxStatus.get(mtval)[1] + 1;
                    } else {
                        maxStatus.put(mtval, new Integer[] { 1, res.getHealthStatus().intValue() });
                    }
                    if (mtTraceId == mtval) {
                        traceResList.add(res);
                    }
                }

            }

            for (MonitorType type : mtList) {
                JSONObject mtjson = genMonitorTypeNode(type, set);
                if (nodeTrace.contains(mtjson.getString("id")) && nodeTrace.size() > 1) {
                    //继续编历并展开其子节点
                    mtjson.element("open", true);
                    loadTraceNode(mtjson, traceResList, nodeTrace, relationTypeIds);
                }
                if (maxStatus.containsKey(type.getId().longValue())) {
                    Integer[] status = maxStatus.get(type.getId().longValue());
                    mtjson.element("name", type.getName() + " (" + status[1] + ")");
                    mtjson.element("iconSkin", "type" + status[0]);
                    statusMap.put(mtjson.getString("id"), status);
                } else {
                    mtjson.element("name", type.getName());
                    mtjson.element("iconSkin", "type1");
                    statusMap.put(mtjson.getString("id"), new Integer[] { 1, 0 });
                }
                jsonArray.add(mtjson);
            }

        } catch (Exception ex) {
            logger.error("error genernate base tree", ex);
        }
        return jsonArray;
    }

    private void loadTraceNode(JSONObject parentNode, List<Res> traceResList, List<String> nodeTrace, Set<Long> relationTypeIds) {
        String[] idArr = parentNode.getString("id").split("[|]");
        JSONArray jsonArray = new JSONArray();
        long mtId = Long.parseLong(idArr[1]);
        List<ResGroup> groups = resGroupCache.findByMoitTypeId(mtId);
        Map<Long, List<ResGroup>> tmpMap = new HashMap<Long, List<ResGroup>>();
        List<ResGroup> rootResGroup = new ArrayList<ResGroup>();
        if (groups == null) {
            groups = new ArrayList<ResGroup>(0);
        }
        List<Long> clickMonitorCache = (List<Long>) request.getSession().getAttribute("clickedMoiType");
        clickMonitorCache.add(mtId);
        for (ResGroup g : groups) {
            if (g.getParentId() != null) {
                List<ResGroup> arr = tmpMap.get(g.getParentId().longValue());
                if (arr == null) {
                    arr = new ArrayList<ResGroup>();
                    tmpMap.put(g.getParentId().longValue(), arr);
                }
                arr.add(g);
            } else {
                rootResGroup.add(g);
            }
        }
        Set<Long> includeList = new HashSet<Long>();
        for (ResGroup g : rootResGroup) {
            JSONObject json = genResGroupNode(g, tmpMap, relationTypeIds, includeList, nodeTrace);
            jsonArray.add(json);
        }

        for (Res res : traceResList) {
            Long mt = resTypeCache.getMoitTypeId(res.getResTypeId());
            if (mt == null || mt.longValue() != mtId || includeList.contains(res.getId().longValue())) {
                continue;
            }
            if (NodePrivilegeUtil.hasResViewPrivilege(res.getId(), relationTypeIds, request)) {
                JSONObject resjson = genResNode(res, 0L, relationTypeIds);
                if (nodeTrace.contains(resjson.getString("id"))) {
                    loadResNodeTrace(resjson, nodeTrace, relationTypeIds);
                }
                jsonArray.add(resjson);
            }
        }
        parentNode.element("children", jsonArray);
    }

    public String refreshTreeNode() {
        Map<String, Integer[]> map = NodePrivilegeUtil.getStatusCache(request, this.viewId);
        Set<Map.Entry<String, Integer[]>> values = map.entrySet();
        List<String[]> statusList = new ArrayList<String[]>();
        List<String[]> resList = new ArrayList<String[]>();
        Set<Long> relationTypeIds = resRelationService.getSelfAndSubRelationTypeIds();
        List<MonitorType> mtList = resViewService.findAllMonitorType();
        Collection<Res> ress = resService.findAll();
        Set<Long> set = new HashSet<Long>();
        Map<Long, Integer[]> maxStatus = new HashMap<Long, Integer[]>();
        for (Res res : ress) {
            if (resTypeCache.getMoitTypeId(res.getResTypeId()) == null) {
                continue;
            }
            if (NodePrivilegeUtil.hasResViewPrivilege(res.getId(), relationTypeIds, request)) {
                long mtval = resTypeCache.getMoitTypeId(res.getResTypeId());
                set.add(mtval);
                if (maxStatus.containsKey(mtval)) {
                    if (maxStatus.get(mtval)[0] < res.getHealthStatus()) {
                        maxStatus.get(mtval)[0] = res.getHealthStatus();
                    }
                    maxStatus.get(mtval)[1] = maxStatus.get(mtval)[1] + 1;
                } else {
                    maxStatus.put(mtval, new Integer[] { 1, res.getHealthStatus() });
                }

            }
        }
        for (MonitorType type : mtList) {
            String nodeId = TreeConstants.NODE_TYPE_MONITORTYPE + "|" + type.getId() + "|0";
            Integer[] olds = map.get(nodeId);
            int newStatus = 1;
            int newResnum = 0;
            if (maxStatus.containsKey(type.getId().longValue())) {
                Integer[] status = maxStatus.get(type.getId().longValue());
                newResnum = status[1];
                newStatus = status[0];
                map.put(nodeId, status);
            }

            if (newResnum != olds[1]) {
                resList.add(new String[] { nodeId, type.getName() + "(" + newResnum + ")" });
            }
            if (newStatus != olds[0]) {
                statusList.add(new String[] { nodeId, "type" + newStatus });
            }

        }
        Map<String, Integer[]> oldResGroups = new HashMap<String, Integer[]>();
        for (Map.Entry<String, Integer[]> entry : values) {
            String[] nodeIds = entry.getKey().split("[|]");
            int oldStatus = entry.getValue()[0];
            if (nodeIds[0].equals("4")) {
                continue;
            } else if (nodeIds[0].equals("2")) {
                //资源节点
                Res res = resService.get(Long.parseLong(nodeIds[1]));
                if (res == null) {
                    continue;
                }
                int currentStatus = res.getPaused() == 1 ? 0 : res.getHealthStatus();
                if (currentStatus != oldStatus) {
                    statusList.add(new String[] { entry.getKey(), "res" + currentStatus });
                    map.put(entry.getKey(), new Integer[] { currentStatus, 0 });
                }
            } else if (nodeIds[0].equals("3")) {
                //资源类别节点
                List<ResBean> children = resService.findChildren(Long.parseLong(nodeIds[2]), Long.parseLong(nodeIds[1]));
                int tmpStatus = 0;
                int pausedSize = 0;
                for (int i = 0; i < children.size(); i++) {
                    Res cRes = children.get(i).res();
                    if (cRes.getHealthStatus() > tmpStatus) {
                        tmpStatus = cRes.getHealthStatus();
                    }
                    if (cRes.getPaused() == 1) {
                        pausedSize++;
                    }
                }
                int currentStatus = children.size() == pausedSize ? 0 : tmpStatus;
                if (oldStatus != currentStatus) {
                    Object[] objs = new Object[2];
                    objs[0] = entry.getKey();
                    objs[1] = "type" + currentStatus;
                    statusList.add(new String[] { entry.getKey(), "type" + currentStatus });
                    map.put(entry.getKey(), new Integer[] { currentStatus, 0 });
                }
            } else {
                oldResGroups.put(entry.getKey(), entry.getValue());
            }
        }
        if (oldResGroups.size() > 0) {
            //说明有资源组已展开
            List<Long> motiTypes = (List<Long>) request.getSession().getAttribute("clickedMoiType");
            for (Long mtId : motiTypes) {
                List<ResGroup> rootResGroup = new ArrayList<ResGroup>();
                List<ResGroup> groups = resGroupCache.findByMoitTypeId(mtId);
                if (groups == null) {
                    groups = new ArrayList<ResGroup>(0);
                }
                Map<Long, List<ResGroup>> tmpMap = new HashMap<Long, List<ResGroup>>();
                for (ResGroup g : groups) {
                    if (g.getParentId() != null) {
                        List<ResGroup> arr = tmpMap.get(g.getParentId().longValue());
                        if (arr == null) {
                            arr = new ArrayList<ResGroup>();
                            tmpMap.put(g.getParentId().longValue(), arr);
                        }
                        arr.add(g);
                    } else {
                        rootResGroup.add(g);
                    }
                }

                for (ResGroup g : rootResGroup) {
                    refreshResGroupNode(g, tmpMap, relationTypeIds, statusList, resList, oldResGroups);
                }
            }
        }
        Struts2Utils.renderJson(new List[] { statusList, resList });
        return null;
    }

    private Integer[] refreshResGroupNode(ResGroup g, Map<Long, List<ResGroup>> childMap, Set<Long> relationTypesIds, List<String[]> statusList, List<String[]> resList, Map<String, Integer[]> oldResGroups) {
        long pid = g.getParentId() == null ? 0 : g.getParentId();
        String nodeId = TreeConstants.NODE_TYPE_RESGROUP + "|" + g.getId() + "|" + pid;
        List<MotiResRel> relList = motiResRelCache.findByResGroupId(g.getId());
        int maxStatus = 1;
        if (childMap.containsKey(g.getId().longValue())) {
            List<ResGroup> children = childMap.get(g.getId().longValue());
            for (ResGroup child : children) {
                Integer[] childJson = refreshResGroupNode(child, childMap, relationTypesIds, statusList, resList, oldResGroups);
                if (maxStatus < childJson[0]) {
                    maxStatus = childJson[0];
                }
            }
        }
        if (relList != null) {
            for (MotiResRel rel : relList) {
                Res res = null;
                if ((res = resService.get(rel.getResId())) != null && NodePrivilegeUtil.hasResViewPrivilege(res.getId(), relationTypesIds, request)) {
                    if (maxStatus < res.getHealthStatus()) {
                        maxStatus = res.getHealthStatus();
                    }
                }
            }
        }
        if (oldResGroups.containsKey(nodeId)) {
            Integer[] olds = oldResGroups.get(nodeId);
            if (olds[0] != maxStatus) {
                statusList.add(new String[] { nodeId, "type" + maxStatus });
            }

        }
        Integer[] newVal = new Integer[] { maxStatus, 0 };
        NodePrivilegeUtil.getStatusCache(request, this.viewId).put(nodeId, newVal);
        return newVal;
    }

    private JSONObject genMonitorTypeNode(MonitorType mt, Set<Long> set) {
        JSONObject json = new JSONObject();
        String nodeId = TreeConstants.NODE_TYPE_MONITORTYPE + "|" + mt.getId() + "|0";
        json.element("id", nodeId);
        boolean isparent = set.contains(mt.getId()) || (resGroupCache.findByMoitTypeId(mt.getId()) != null);
        json.element("isParent", isparent);
        return json;
    }

    private JSONObject genResGroupNode(ResGroup g, Map<Long, List<ResGroup>> childMap, Set<Long> relationTypesIds, Set<Long> includeList, List<String> traceList) {
        JSONObject json = new JSONObject();
        long pid = g.getParentId() == null ? 0 : g.getParentId();
        String nodeId = TreeConstants.NODE_TYPE_RESGROUP + "|" + g.getId() + "|" + pid;
        json.element("id", nodeId);
        if (traceList.contains(nodeId)) {
            json.element("open", true);
        }
        List<MotiResRel> relList = motiResRelCache.findByResGroupId(g.getId());
        JSONArray arr = new JSONArray();
        int maxStatus = 1;
        if (childMap.containsKey(g.getId().longValue())) {
            List<ResGroup> children = childMap.get(g.getId().longValue());
            for (ResGroup child : children) {
                JSONObject childJson = genResGroupNode(child, childMap, relationTypesIds, includeList, traceList);

                if (maxStatus < childJson.getInt("maxStatus")) {
                    maxStatus = childJson.getInt("maxStatus");
                }
                arr.add(childJson);
            }
        }
        if (relList != null) {
            for (MotiResRel rel : relList) {
                Res res = null;
                if ((res = resService.get(rel.getResId())) != null && NodePrivilegeUtil.hasResViewPrivilege(res.getId(), relationTypesIds, request)) {
                    JSONObject resjson = genResNode(res, 0L, relationTypesIds);
                    if (traceList.contains("2|" + res.getId() + "|0")) {
                        loadResNodeTrace(resjson, traceList, relationTypesIds);
                    }
                    arr.add(resjson);
                    includeList.add(res.getId().longValue());
                    if (maxStatus < res.getHealthStatus()) {
                        maxStatus = res.getHealthStatus();
                    }
                }
            }
        }
        json.element("maxStatus", maxStatus);
        json.element("iconSkin", "type" + maxStatus);
        json.element("name", g.getName());
        NodePrivilegeUtil.getStatusCache(request, this.viewId).put(nodeId, new Integer[] { maxStatus, 0 });
        json.element("children", arr);
        return json;
    }

}
